/**
 * 创建一个环形状态元素
 elId:目标元素id
 percentage: 百分比 0-100
 callback: 回调函数
 */
const circularPattern =function(options) {
    let _options = {
        elId:'',
        percentage:'',
        border:9,
        color:{
            background:'#E6E6E6',
            prospect:'#4CAF50',
            highlight:'rgba(0, 255, 0, 0.8)'
        },
        intervalTimeout:1500,
        callback:undefined,
        mousemove:undefined,
        click:undefined
    }
    function CreateCircularPattern(options) {
        var startTime;
        var canvas,ctx ;
        var highlight = {
            value: false,
            set:function (value){
                if (value && !this.value){
                    this.value = value
                    _drawCircularProgress(circle.endAngle/100);
                }

                if (!value && this.value){
                    this.value = value
                    _drawCircularProgress(circle.endAngle/100);
                }
            }
        };
        var targetElement = {};
        var circle={x: 0, y: 0, radius: 0, startAngle: 0, endAngle: 0, anticlockwise: false,border:options.border}
        {
            _getTargetElement();
            _createCanvas();
            //_drawCircularProgress();
            requestAnimationFrame(animate);
            if (typeof options.callback === 'function') {
                setInterval(options.callback(),options.intervalTimeout);
            }
            _canvasAddEventListener();
        }

        this.updateCircularProgress = function (percentage){
            circle.endAngle = percentage;
            requestAnimationFrame(animate);
        }
        // 获取canvas元素
        this.getTargetElement = function () {
            return targetElement.element;
        }


        /**
         * 获取目标元素
         */
        function _getTargetElement(){
            targetElement.element = document.getElementById(options.elId);
            // 获取元素的内边距
            let computedStyle = window.getComputedStyle(targetElement.element);
            targetElement.width = targetElement.element.offsetWidth - (parseFloat(computedStyle.paddingLeft)+parseFloat(computedStyle.paddingRight));
            targetElement.height = targetElement.element.offsetHeight- (parseFloat(computedStyle.paddingTop)+parseFloat(computedStyle.paddingBottom));
            targetElement.min = function (){
                return (Math.min(this.width,this.height))
            }
        }

        /**
         * 创建画布
         */
        function _createCanvas(){
            canvas = document.createElement('canvas');
            canvas.id = 'canvas-'+options.elId;
            let devicePixelRatio = window.devicePixelRatio || 1;
            // 设置 canvas 的宽度和高度
            canvas.width = targetElement.min() * devicePixelRatio;
            canvas.height = targetElement.min() * devicePixelRatio;

            // 将 canvas 添加到页面的 body 元素中
            targetElement.element.appendChild(canvas);
            // 获取绘图上下文
            ctx = canvas.getContext('2d');
            ctx.canvas.willReadFrequently = true;
            ctx.imageSmoothingEnabled = true;
            ctx.imageSmoothingQuality = 'high';
            ctx.scale(devicePixelRatio, devicePixelRatio);

            // 保存圆环信息
            var radius = (canvas.width / 2)-5;
            circle.x= radius ;
            circle.y= radius ;
            circle.radius = (radius - circle.border / 2);
            circle.endAngle = options.percentage;
        }
        // 添加监听事件
        function _canvasAddEventListener(){
            let canvas = document.getElementById('canvas-'+options.elId)
            if (typeof options.mousemove === 'function') {
                canvas.addEventListener('mousemove', function (e) {
                    const rect =  canvas.getBoundingClientRect();
                    const mouseX = e.clientX ;
                    const mouseY = e.clientY ;
                    let color = _getPixelColor(mouseX,mouseY,rect);
                    var mouseOverRect = isMouseOverRect(mouseX, mouseY, rect);
                    if (mouseOverRect && color === options.color.prospect) {
                        highlight.set(true) ;
                        options.mousemove(e,canvas)
                    }else if (mouseOverRect && color === options.color.background){
                        highlight.set(true) ;
                        options.mousemove(e,canvas)
                    }else {
                        highlight.set(false);
                    }
                });
            }
            if (typeof options.click === 'function') {
                canvas.addEventListener('click', function (e) {
                    const rect =  canvas.getBoundingClientRect();
                    const mouseX = e.clientX ;
                    const mouseY = e.clientY ;

                    let color = _getPixelColor(mouseX,mouseY,rect);
                    if (isMouseOverRect(mouseX, mouseY, rect) && color === options.color.prospect){
                        options.click(e,canvas)
                    }
                    if (isMouseOverRect(mouseX, mouseY, rect) && color === options.color.background){
                        options.click(e,canvas)
                    }
                });
            }
        }

        // 鼠标事件处理
        function isMouseOverRect(x, y, rect) {
            return x >= rect.x && x <= rect.x + rect.width &&
                y >= rect.y && y <= rect.y + rect.height;
        }

        // 颜色转化
        function _rgbToHex(r,g,b){
            r = Math.max(0, Math.min(255, r));
            g = Math.max(0, Math.min(255, g));
            b = Math.max(0, Math.min(255, b));
            return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase();
        }
        function _getPixelColor(x, y,rect) {
            x = x - rect.left;
            y = y - rect.top;
            let imageData = ctx.getImageData(x, y, 1, 1);
            let [r, g, b, a] = imageData.data;
            return _rgbToHex(r,g,b);
        }

        /**
         * 绘制内容
         */
        function _drawBackground(){
            // Draw background circle
            ctx.beginPath();
            ctx.arc(circle.x, circle.y,circle.radius, 0, Math.PI*2);
            ctx.lineWidth = circle.border;
            ctx.strokeStyle = options.color.background;
            ctx.stroke();
        }
        function _drawUseProgress(currentProgress){
            let startAngle =  1.5 * Math.PI;
            let endAngle = startAngle + ((currentProgress) * 2 * Math.PI);

            ctx.beginPath();
            ctx.arc(circle.x, circle.y,circle.radius, startAngle, endAngle,circle.anticlockwise);
            ctx.lineWidth = circle.border;
            ctx.strokeStyle = options.color.prospect; // Progress color

            if (highlight.value){
                ctx.shadowColor = options.color.highlight;
                ctx.shadowBlur = 5; // Amount of glow
                ctx.shadowOffsetX = 0;
                ctx.shadowOffsetY = 0;
                ctx.stroke();
            }else {
                ctx.stroke();
            }

            const angle = 2 * Math.PI * currentProgress - Math.PI / 2;
            const dotX = circle.x + circle.radius * Math.cos(angle);
            const dotY = circle.y + circle.radius * Math.sin(angle);

            ctx.beginPath();
            ctx.arc(dotX, dotY, 4, 0, 2 * Math.PI, false);
            ctx.fillStyle = options.color.prospect;
            ctx.fill();
            if (highlight.value){
                // 清除阴影设置
                ctx.shadowColor = 'transparent';
                ctx.shadowBlur = 0;
            }
        }
        function _drawText(){
            const fontSize = Math.min(circle.radius * 0.4, 48);
            ctx.font = `${fontSize}px Arial`;
            ctx.fillStyle = 'black';
            ctx.textAlign = 'center';
            ctx.textBaseline = 'middle';
            ctx.fillText(circle.endAngle+"%", circle.x, circle.y);
        }

        function _drawCircularProgress(percentage) {
            // Clear canvas
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            _drawBackground();
            _drawUseProgress(percentage);
            _drawText();
        }



        function animate(timestamp) {
            if (!startTime) startTime = timestamp;
            const progress = (timestamp - startTime) / 1000;
            let percent = Math.min(progress, (circle.endAngle/100)) / (circle.endAngle/100);
            percent = Math.min(progress, (circle.endAngle/100));
            _drawCircularProgress(percent);
            if (progress < 1 && percent*100 < circle.endAngle) {
                requestAnimationFrame(animate);
            }
        }
    }
    if (typeof options !== 'object'){
        throw new Error('options is not object');
    }
    if (!options.elId || options.elId === '' || options.elId === null || options.elId === undefined){
        throw new Error('options.elId is null');
    }
    return new CreateCircularPattern({..._options,...options});
}
